package com.cly.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cly.base.contants.CacheKeysConstants;
import com.cly.base.entity.BaseEntity;
import com.cly.course.SubjectFeign;
import com.cly.dto.ProblemInsertDto;
import com.cly.entity.Problem;
import com.cly.entity.ProblemOption;
import com.cly.entity.Subject;
import com.cly.enums.ProblemTypeEnum;
import com.cly.mapper.ProblemMapper;
import com.cly.result.JsonRequest;
import com.cly.result.exception.ServiceException;
import com.cly.result.exenum.RequestException;
import com.cly.service.IProblemBankService;
import com.cly.service.IProblemOptionService;
import com.cly.service.IProblemService;
import com.cly.vo.ProblemDetailVo;
import com.cly.vo.ProblemVo;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 题目表 服务实现类
 *
 * @author by 春风能解释
 * <p>
 * 2024-06-05
 */
@Service
@RequiredArgsConstructor
public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> implements IProblemService {


    /**
     * 科目表远程服务
     */
    private final SubjectFeign subjectFeign;

    /**
     * 题目选项表服务
     */
    private final IProblemOptionService problemOptionService;

    /**
     * 题库服务
     */
    private final IProblemBankService problemBankService;

    /**
     * 分页查询题目
     *
     * @param current 页码
     * @param size    页长
     * @param problem 条件
     * @return JSON
     */
    @Override
    @Cacheable(value = CacheKeysConstants.ExamKeys.PROBLEM_ARRAY, key = "#root.args")
    public JsonRequest<List<ProblemVo>> lookProblem(Integer current, Integer size, Problem problem) {
        IPage<ProblemVo> page = baseMapper.lookProblem(new Page<>(current, size), problem);
        List<ProblemVo> problems = page.getRecords();
        if (problems.isEmpty()) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        // 查询科目
        List<Long> subjectId = problems.stream()
                .map(Problem::getSubjectId)
                .toList();
        JsonRequest<Map<Long, Subject>> mapJsonRequest = subjectFeign.lookSubjectMap(subjectId);
        // 设置科目名称
        if (mapJsonRequest.getSuccess()) {
            Map<Long, Subject> map = mapJsonRequest.getData();
            problems.forEach(v -> v.setSubjectName(map.get(v.getSubjectId()).getName()));
        }
        // 传入分页
        return JsonRequest.success(problems, page.getTotal());
    }

    /**
     * 查看题目详情
     *
     * @param id ID
     * @return JSON
     */
    @Override
    @Cacheable(value = CacheKeysConstants.ExamKeys.PROBLEM_ARRAY, key = "#id")
    public JsonRequest<ProblemDetailVo> lookProblemDetail(Long id) {
        ProblemVo problemVo = baseMapper.lookProblemDetail(id);
        if (Objects.isNull(problemVo)) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        JsonRequest<Map<Long, Subject>> mapJsonRequest = subjectFeign.lookSubjectMap(Collections.singletonList(problemVo.getSubjectId()));
        if (mapJsonRequest.getSuccess()) {
            Map<Long, Subject> data = mapJsonRequest.getData();
            problemVo.setSubjectName(data.get(problemVo.getSubjectId()).getName());
        }
        ProblemDetailVo problemDetailVo = BeanUtil.copyProperties(problemVo, ProblemDetailVo.class);
        if (problemDetailVo.getType().equals(ProblemTypeEnum.SHORT_ANSWER.getValue())) {
            return JsonRequest.success(problemDetailVo);
        }
        List<ProblemOption> problemOptions = problemOptionService.list(Wrappers
                .lambdaQuery(ProblemOption.class)
                .in(ProblemOption::getProblemId, problemVo.getId()));
        problemDetailVo.setOptions(problemOptions);
        return JsonRequest.success(problemDetailVo);
    }

    /**
     * 添加一条题目
     *
     * @param problem 题目实体
     * @return JSON
     */
    @Override
    @CacheEvict(value = {CacheKeysConstants.ExamKeys.PROBLEM_ARRAY, CacheKeysConstants.ExamKeys.EXAM_COUNT, CacheKeysConstants.ExamKeys.EXAM_TYPE}, allEntries = true)
    public JsonRequest<Integer> addOneProblem(ProblemInsertDto problem) {
        int column = baseMapper.insert(problem);
        if (column < 1) {
            throw new ServiceException(RequestException.INSERT_ERROR);
        }
        JsonRequest<Integer> jsonRequest = problemOptionService.insertOption(problem.getOptions(), problem.getType(), problem.getId());
        if (!jsonRequest.getSuccess()) {
            throw new ServiceException(RequestException.INSERT_ERROR);
        }
        problemBankService.insertProblem(problem);
        return JsonRequest.success(column);
    }

    /**
     * 修改一条题目
     *
     * @param problem 题目实体
     * @return JSON
     */
    @Override
    @CacheEvict(value = {CacheKeysConstants.ExamKeys.PROBLEM_ARRAY, CacheKeysConstants.ExamKeys.EXAM_COUNT, CacheKeysConstants.ExamKeys.EXAM_TYPE}, allEntries = true)
    public JsonRequest<Integer> updateOneProblem(ProblemInsertDto problem) {
        Problem problem1 = getById(problem.getId());
        if (Objects.isNull(problem1)) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        // 删除选项
        problemOptionService
                .remove(Wrappers.lambdaQuery(ProblemOption.class)
                        .in(ProblemOption::getProblemId, problem.getId()));
        JsonRequest<Integer> jsonRequest = problemOptionService.insertOption(problem.getOptions(), problem.getType(), problem.getId());
        if (!jsonRequest.getSuccess()) {
            throw new ServiceException(RequestException.INSERT_ERROR);
        }
        // 判断题库是否修改
        if (!problem.getBankId().equals(problem1.getBankId())) {
            problemBankService.insertProblem(problem);
            problemBankService.removeProblem(List.of(problem1));
        }
        return JsonRequest.success(baseMapper.updateById(problem));
    }

    /**
     * 批量删除题目
     *
     * @param ids id数组
     * @return JSON
     */
    @Override
    @CacheEvict(value = {CacheKeysConstants.ExamKeys.PROBLEM_ARRAY, CacheKeysConstants.ExamKeys.EXAM_COUNT, CacheKeysConstants.ExamKeys.EXAM_TYPE}, allEntries = true)
    public JsonRequest<Integer> deleteProblems(List<Long> ids) {
        List<Problem> problems = listByIds(ids);
        if (problems.size() != ids.size()) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        // 获取非简答题的id
        List<Long> problemIds = problems
                .stream()
                .filter(v -> !v.getType().equals(ProblemTypeEnum.SHORT_ANSWER.getValue()))
                .map(BaseEntity::getId)
                .distinct()
                .toList();
        // 删除选项
        problemOptionService
                .remove(Wrappers.lambdaQuery(ProblemOption.class)
                        .in(ProblemOption::getProblemId, problemIds));
        // 更新题库信息
        JsonRequest<Boolean> jsonRequest = problemBankService.removeProblem(problems);
        if (!jsonRequest.getSuccess()) {
            throw new ServiceException(RequestException.DELETE_ERROR);
        }
        return JsonRequest.success(baseMapper.deleteByIds(ids));
    }


}




